package org.gpf.game.tank.offline;

import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;

import org.gpf.game.tank.offline.Tank.Direction;
/**
 * 坦克游戏的主窗口
 * 该类就是一个大管家（调停者设计模式）
 * @author gaopengfei
 * @date 2015-5-3 下午7:54:46
 */
@SuppressWarnings("serial")
public class TankClient extends Frame {

	public static final int GAME_WIDTH = 640;
	public static final int GAME_HEIGHT = 480;
	
	private static final int SCREEN_WIDTH = Toolkit.getDefaultToolkit().getScreenSize().width;
	private static final int SCREEN_HEIGHT = Toolkit.getDefaultToolkit().getScreenSize().height;
	
	Tank myTank = new Tank(50,50,true,Direction.STOP,this); 			// 创建主站坦克并制定起始位置
	List<Missile> missiles = new ArrayList<Missile>();	// 该容器用来装子弹
	List<Explode> explodes = new ArrayList<Explode>();	// 一个游戏中可能有多个爆炸
	List<Tank> tanks = new ArrayList<Tank>();			// 敌方坦克
	
	Wall w1 = new Wall(100, 200, 20, 250, this), w2 = new Wall(300, 100, 400, 20, this);//两堵墙
	
	Blood b = new Blood();	// 加血的药
	
	Image offScreenImage = null;
	
	/**
	 * 构造方法中初始化窗口的各个属性，并显示窗口
	 */
	public TankClient() {
		
		for (int i = 0; i < 15; i++) {
			tanks.add(new Tank(50 + 40 * i, 50 + i * 20, false, Direction.D, this));
		}

		this.setTitle("坦克大战-单机版");
		this.setBounds((SCREEN_WIDTH - GAME_WIDTH)/2, (SCREEN_HEIGHT - GAME_HEIGHT)/2, GAME_WIDTH, GAME_HEIGHT);
		this.setResizable(false);
		this.setBackground(Color.PINK);	// JFrame的背景颜色设置存在bug，这里用Frame
		this.addWindowListener(new WindowAdapter() {
			
			@Override
			public void windowClosing(WindowEvent e) {

				System.exit(0);
			}
		});
		this.setVisible(true);
		
		this.addKeyListener(new KeyMonitor());
		
		new Thread(new PaintThread()).start(); 			// 启动绘图线程
	}
	
	@Override
	public void paint(Graphics g) {
		
		// 游戏的调试信息
		g.drawString("子弹数量：" + missiles.size(), 550, 400);
		g.drawString("爆炸数量：" + explodes.size(), 550, 420);
		g.drawString("坦克数量：" + tanks.size(), 550, 440);
		g.drawString("生命值：" + myTank.getLife(), 550, 460);
		
		// 敌人死光了
		if(tanks.size() <= 0){
			for (int i = 0; i < 5; i++) {
				tanks.add(new Tank(50 + 40 * i, 50 + i * 20, false, Direction.D, this));
			}
		}
		
		// 画子弹
		for (int i = 0; i < missiles.size(); i++) {
			Missile m = missiles.get(i);			//	取出每一颗子弹，并绘制
			m.hitTanks(tanks);						// 取出一个子弹打坦克
			m.hitTank(myTank);						// 敌军攻击我方坦克
			m.hitWall(w1);
			m.hitWall(w2);
//			if (!m.isLive())
//				missiles.remove(m);					// 如果子弹死亡就将其从容器中移除
//			else 
//				m.draw(g);
			m.draw(g);
		}
		
		//　画爆炸
		for (int i = 0; i < explodes.size(); i++) {
			Explode e = explodes.get(i);
			e.draw(g);
		}
		
		// 画敌方坦克（多个）
		for (int i = 0; i < tanks.size(); i++) {
			Tank t = tanks.get(i);
			t.collidesWithWall(w1);
			t.collidesWithWall(w2);
			t.collidesWithTanks(tanks);
			t.draw(g);
		}
		
		myTank.draw(g); // 绘制主站坦克【把绘制坦克的方法给坦克自己实现】
		w1.draw(g);
		w2.draw(g);
		b.draw(g);
		myTank.eatBlood(b);
	}
	
	@Override
	public void update(Graphics g) {

		if (offScreenImage == null) {
			offScreenImage = this.createImage(GAME_WIDTH, GAME_HEIGHT);
		}
		Graphics gOffScreen = offScreenImage.getGraphics();
		Color c = gOffScreen.getColor();
		gOffScreen.setColor(Color.PINK);
		gOffScreen.fillRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
		gOffScreen.setColor(c);
		paint(gOffScreen);
		g.drawImage(offScreenImage, 0, 0, null);
	}
	
	/**
	 * 该线程用于每隔一段时间绘制一次图形，更新坦克的位置【因为服务于TankClient，定义为内部类比较合适】
	 */
	private class PaintThread implements Runnable{

		@Override
		public void run() {

			while (true) {
				repaint();
				try {
					Thread.sleep(50);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
		
	}
	
	/**
	 * 键盘监听器
	 */
	private class KeyMonitor extends KeyAdapter{
		
		/**
		 * 方向键按下的时候移动坦克
		 */
		@Override
		public void keyPressed(KeyEvent e) {

			myTank.keyPressed(e); // 具体的实现操作交给坦克自身完成
		}
		
		/**
		 * 键盘抬起的时候停止移动
		 */
		@Override
		public void keyReleased(KeyEvent e) {
			
			myTank.keyReleased(e);
		}
	}
	
	public static void main(String[] args) {
		new TankClient();
	}

}
